Olaf adds Support for Navigon Mobile Navigator 5 Palm/OS files.
authorrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 13 Sep 2005 20:11:39 +0000 (20:11 +0000)
committerrobertl <robertl@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Tue, 13 Sep 2005 20:11:39 +0000 (20:11 +0000)
Refactor is_fatal and lrtrim to be common code.

gpsbabel/Makefile
gpsbabel/README
gpsbabel/cst.c
gpsbabel/defs.h
gpsbabel/msroute.c
gpsbabel/nmn5.c [new file with mode: 0644]
gpsbabel/pathaway.c
gpsbabel/testo
gpsbabel/util.c
gpsbabel/vecs.c

index 524b29bec91c7c5ceca920be414b2f3e62881830..f89ac1f567c014d279d9330dfa059c87904a6c53 100644 (file)
@@ -39,7 +39,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \
        igc.o brauniger_iq.o shape.o hiketech.o glogbook.o coastexp.o \
        vcf.o overlay.o kml.o google.o lowranceusr.o an1.o tomtom.o \
        tef_xml.o maggeo.o pathaway.o vitosmt.o gdb.o bcr.o coto.o \
-       ignrando.o stmwpp.o msroute.o cst.o
+       ignrando.o stmwpp.o msroute.o cst.o nmn5.o
 
 FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o reverse_route.o sort.o stackfilter.o trackfilter.o discard.o
 
@@ -220,6 +220,8 @@ msroute.o: msroute.c defs.h queue.h gbtypes.h
 navicache.o: navicache.c defs.h queue.h gbtypes.h cet_util.h
 netstumbler.o: netstumbler.c defs.h queue.h gbtypes.h csv_util.h
 nmea.o: nmea.c defs.h queue.h gbtypes.h
+nmn5.o: nmn5.c defs.h queue.h gbtypes.h coldsync/palm.h coldsync/pdb.h \
+  jeeps/gpsmath.h
 overlay.o: overlay.c defs.h queue.h gbtypes.h grtcirc.h
 ozi.o: ozi.c defs.h queue.h gbtypes.h csv_util.h
 palmdoc.o: palmdoc.c defs.h queue.h gbtypes.h jeeps/gpsmath.h jeeps/gps.h \
index c8f1dc0f1dd776fb6e40148c874fd598c685fc0e..14d782a5a10d37e5f0b546247cadbe7ac8add832 100644 (file)
@@ -1084,6 +1084,14 @@ THE FORMATS
        
        http://phgiraud.free.fr/CarteSurTable/CarteSurTable.htm
        
+    nmn5
+    
+       Support for Navigon Mobile Navigator 5 Palm/OS files.
+       This is a route-only format. 
+       
+       http://www.navigon.com
+       
+       
 DATA FILTERS
 
         GPSBabel supports data filtering.  Data filters are invoked from
index 264d3794a85cd59059eb74b36acbf8a42208f279..f3358224275f11d44d410fe80e67bfca3f8702a6 100644 (file)
@@ -52,20 +52,6 @@ arglist_t cst_args[] = {
 
 /* helpers */
 
-static char *
-cst_trim_buff(char *buff)
-{
-       char *c;
-       
-       c = buff + strlen(buff);
-       while ((c >= buff) && ((unsigned char)*c <= ' ')) *c-- = '\0';
-
-       c = buff;
-       while ((*c != '\0') && ((unsigned char)*c <= ' ')) c++;
-       
-       return c;
-}
-
 static void
 cst_add_wpt(const route_head *track, waypoint *wpt)
 {
@@ -188,7 +174,7 @@ cst_data_read(void)
                char *cin = buff;
                
                line++;
-               cin = cst_trim_buff(buff);
+               cin = lrtrim(buff);
                if (strlen(cin) == 0) continue;
                
                if (strncmp(cin, "; ", 2) == 0) continue;
@@ -224,7 +210,7 @@ cst_data_read(void)
                                        
                                        if (strncmp(cin + 2, "bitmap", 6) == 0)
                                        {
-                                               cin = cst_trim_buff(cin + 8);
+                                               cin = lrtrim(cin + 8);
                                                if (*cin != '\0')
                                                        wpt->url = cst_make_url(cin);
                                        }
@@ -232,13 +218,13 @@ cst_data_read(void)
                                        while (NULL != fgets(buff, sizeof(buff), fin))
                                        {
                                                line++;
-                                               cin = cst_trim_buff(buff);
+                                               cin = lrtrim(buff);
                                                
                                                if (strcmp(cin + 2, "note") == 0)
                                                {
                                                        fgets(buff, sizeof(buff), fin);
                                                        line++;
-                                                       cin = cst_trim_buff(buff);
+                                                       cin = lrtrim(buff);
                                                        if (*cin != '\0')
                                                                wpt->notes = xstrdup(cin);
                                                }
@@ -300,7 +286,7 @@ cst_data_read(void)
                                        {
                                                struct tm tm;
                                                
-                                               pow = cst_trim_buff(++pow);
+                                               pow = lrtrim(++pow);
                                                strptime(pow, "%Y %m %d %H:%M:%S", &tm);
                                                
                                                wpt->creation_time = mkgmtime(&tm);
index 2dced8f30998a6e9b1adef5e0b2f2dd91097339b..e7a785f0ac345453e323b0d8236f9a337a8bf8cf 100644 (file)
@@ -523,6 +523,12 @@ void fatal(const char *, ...)
        __attribute__((noreturn))
 #endif
        ;
+void is_fatal(const int condition, const char *, ...);
+#if __GNUC__
+       __attribute__ ((__format__ (__printf__, 1, 2)))
+       __attribute__((noreturn))
+#endif
+
 void warning(const char *, ...)
 #if __GNUC__
        __attribute__ ((__format__ (__printf__, 1, 2)))
@@ -595,6 +601,7 @@ char *strsub(const char *s, const char *search, const char *replace);
 char *gstrsub(const char *s, const char *search, const char *replace);
 char *xstrrstr(const char *s1, const char *s2);
 void rtrim(char *s);
+char * lrtrim(char *s);
 signed int get_tz_offset(void);
 time_t mkgmtime(struct tm *t);
 time_t current_time(void);
index 187e26c0868d91729528f04ad50b04a76f8a4eb8..d85e96c4f1c8b7eb74ab72766cb0fe49d48f7325 100644 (file)
@@ -154,21 +154,6 @@ static int ole_root_sec_ct;
 
 /* local helpers */
 
-static void
-is_fatal(const int condition, const char *fmt, ...)
-{
-       va_list args;
-       char buff[128];
-       
-       if (condition == 0) return;
-       
-       va_start(args, fmt);
-       vsnprintf(buff, sizeof(buff), fmt, args);
-       va_end(args);
-       
-       fatal(MYNAME ": %s\n", buff);
-}
-
 static void
 print_buff(const char *buff, int count, const char *comment)
 {
diff --git a/gpsbabel/nmn5.c b/gpsbabel/nmn5.c
new file mode 100644 (file)
index 0000000..2092898
--- /dev/null
@@ -0,0 +1,217 @@
+/* 
+
+       Support for Navigon Mobile Navigator Palm/OS pdb files,
+
+       Copyright (C) 2005 Olaf Klein, o.b.klein@t-online.de
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program; if not, write to the Free Software
+       Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+*/
+
+#include <ctype.h>
+#include <math.h>
+
+#include "defs.h"
+#include "coldsync/palm.h"
+#include "coldsync/pdb.h"
+#include "jeeps/gpsmath.h"
+
+#define MYNAME "nmn5"
+
+#define NMN5_MAGIC     0x766d6170              /* vmap */
+#define NMN5_ROUTE     0x49444154              /* IDAT */
+
+FILE *fd_in;
+static struct pdb *pdb_in;
+static char *fname_in;
+
+static arglist_t nmn5_args[] = 
+{
+       {0, 0, 0, 0, 0 }
+};
+
+static double
+nmn5_to_degree(const int degx)
+{
+       int m, d, x;
+       double s, res;
+       
+       d = degx / 100000;
+       x = degx % 100000;
+       m = x / 1000;
+       x = x % 1000;
+       s = (double)(x) / 10;
+       
+       GPS_Math_DegMinSec_To_Deg(d, m, s, &res);
+
+       return res;
+}
+
+static void
+nmn5_read_data(const char *data, const size_t data_len)
+{
+       route_head *route;
+       char *cin = (char *)data;
+       char *cend = cin + data_len;
+       
+       route = route_head_alloc();
+       route_add_head(route);
+       
+       while (cin < cend)
+       {
+               char *lend;
+               int len;
+               
+               lend = strchr(cin, '\x0A');
+               if (lend == NULL) break;
+               
+               len = (lend - cin);
+               if (len > 0)
+               {
+                       *lend = '\0';
+                       
+                       if (case_ignore_strncmp(cin, "Wegname=", 8) == 0)       /* This only works with the german release */
+                       {                                                       /* test-data created with other releases are welcome */
+                               cin += 8;
+                               if (*cin != '\0')
+                                       route->rte_name = xstrdup(cin);
+                       }
+                       else if (case_ignore_strncmp(cin, "Fahrzeit=", 9) == 0)
+                       {
+                       }
+                       else if (case_ignore_strncmp(cin, "Kosten=", 7) == 0)
+                       {
+                       }
+                       else
+                       {
+                               char *buff, *comma;
+                               
+                               /* now we are looking for a sequence like 0,1 NE (123456,654321) */
+                                 
+                               buff = xmalloc(strlen(cin) + 1);                /* safe target space for sscanf( ... */
+                       
+                               comma = cin;
+                               while ((comma = strchr(comma, ',')))
+                               {
+                                       int i, xlat, xlon;
+                                       waypoint *wpt;
+                                       char *cx;
+                               
+                                       comma++;
+                                       
+                                       if (isdigit(*comma) == 0) continue;
+                                       if (isdigit(*(comma - 2)) == 0) continue;
+                                       
+                                       if (4 != sscanf(comma, "%d %s (%d,%d)", &i, buff, &xlon, &xlat)) continue;
+                                       if (strchr("NESW", *buff) == NULL) continue;    /* north, east, ... */
+                                       
+                                       cx = comma - 2;                         /* go left over delta distance */
+                                       while (isdigit(*cx) != 0) *cx-- = '\0';
+                                       cin = lrtrim(cin);
+                                       
+                                       for (i = 0; i < 2; i++)                 /* skip time and distance at start of line */
+                                       {
+                                               cin = strchr(cin, ' ');
+                                               cin = lrtrim(cin);
+                                       }
+
+                                       wpt = waypt_new();
+                                       
+                                       wpt->latitude = nmn5_to_degree(xlat);
+                                       wpt->longitude = nmn5_to_degree(xlon);
+                                       wpt->description = xstrdup(cin);
+                                       
+                                       cx = strchr(comma, ')');                /* find tailing notes after the coordinates */
+                                       if (cx != NULL) 
+                                       {
+                                               char *tail = lrtrim(++cx);
+                                               if (*tail != '\0')
+                                               {
+                                                       wpt->notes = xstrdup(tail);
+                                               }
+                                       }
+                                       if (*cin != '-')
+                                               waypt_add(waypt_dupe(wpt));
+                                               
+                                       route_add_wpt(route, wpt);
+                                       
+                                       break;
+                               }
+                               xfree(buff);
+                       }
+
+               }
+               cin = lend + 1;
+       }
+}
+
+/* ============================================================================================
+ * &&& gobal callbacks &&&
+ * ----------------------------------------------------------------------------------------- */
+
+static void nmn5_rd_init(const char *fname)
+{
+       fname_in = xstrdup(fname);
+       fd_in = xfopen(fname, "rb", MYNAME);
+}
+
+static void nmn5_rd_deinit(void)
+{
+       fclose(fd_in);
+       xfree(fname_in);
+}
+
+static void nmn5_read(void)
+{
+       struct pdb_record *pdb_rec = NULL;
+
+       
+       pdb_in = pdb_Read(fileno(fd_in));
+       is_fatal((pdb_in == NULL), "read failed.");
+           
+       is_fatal((pdb_in->creator != NMN5_MAGIC),       /* identify the database */
+               "Not a NMN5 pdb file (0x%08x).", pdb_in->creator);
+
+       is_fatal((pdb_in->version != 0),                /* only version "0" currently seen and tested */
+               "This file is from an unsupported version (%d) of NMN5 and is unsupported.", pdb_in->version + 5);
+
+       is_fatal((pdb_in->type != NMN5_ROUTE),
+               "Unknown pdb data type (0x%08x).", pdb_in->type);
+
+       for (pdb_rec = pdb_in->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) 
+       {
+               char *data = (char *)pdb_rec->data;
+
+               if (be_read16(data) == 0)
+                       nmn5_read_data(data + 3, pdb_rec->data_len - 3);
+       }
+       free_pdb(pdb_in);
+}
+
+/* ======================================================================================= */
+
+ff_vecs_t nmn5_vecs = {
+       ff_type_file,
+       { ff_cap_read, ff_cap_none, ff_cap_read },      /* real route + emulated waypoints */
+       nmn5_rd_init,   
+       NULL,   
+       nmn5_rd_deinit,
+       NULL,
+       nmn5_read,
+       NULL,
+       NULL, 
+       nmn5_args,
+       CET_CHARSET_MS_ANSI, 1  /* CET-REVIEW */
+};
index 3e06745a06535dab308a6252ab449eb8a84e30b8..909b3e25a4b0edc5ecbf173ddf533d4f83a5cbec 100644 (file)
@@ -69,12 +69,6 @@ static arglist_t ppdb_args[] =
        {0, 0, 0, 0, 0 }
 };
 
-static void 
-is_fatal(int is, const char *msg, ... )
-{
-    if (is) fatal(MYNAME ": %s\n", msg);
-}
-
 #define PPDB_DEBUG 1
 
 #if PPDB_DEBUG
index 819d5698a34aea0eabcbdf31daf7c1a1bc80ca14..6b2223fbfe602da68d0844870e34a9fa63215c39 100755 (executable)
@@ -866,4 +866,11 @@ rm -f ${TMPDIR}/cst-*
 ${PNAME} -i cst -f reference/route/cst-sample.cst -o gpx -F ${TMPDIR}/cst-sample.gpx
 compare ${TMPDIR}/cst-sample.gpx reference/route/cst-sample.gpx
 
+#
+# Navigon Mobile Navigator 5 .pdb (read-only)
+#
+rm -f ${TMPDIR}/nmn5-sample*
+# ${PNAME} -i nmn5 -f reference/route/nmn5-sample.pdb -o gpx -F ${TMPDIR}/nmn5-sample.gpx
+# compare ${TMPDIR}/nmn5-sample.gpx reference/route/nmn5-sample.gpx
+
 exit 0
index ad4edf43998056958ab40f04d7e4be98032d74cf..48ec95b45de79d3cf4a6f4dbecbcd807ce550676 100644 (file)
@@ -311,6 +311,23 @@ rtrim(char *s)
        }
 }
 
+/*
+ * Like trim, but trims whitespace from both beginning and end.
+ */
+char *
+lrtrim(char *buff)
+{
+       char *c;
+
+       c = buff + strlen(buff);
+       while ((c >= buff) && ((unsigned char)*c <= ' ')) *c-- = '\0';
+
+       c = buff;
+       while ((*c != '\0') && ((unsigned char)*c <= ' ')) c++;
+
+       return c;
+}
+
 /*
  *   Like strcmp, but case insensitive.  Like Berkeley's strcasecmp.
  */
@@ -362,6 +379,21 @@ fatal(const char *fmt, ...)
        exit(1);
 }
 
+void
+is_fatal(const int condition, const char *fmt, ...)
+{
+       va_list args;
+       char buff[128];
+
+       if (condition == 0) return;
+
+       va_start(args, fmt);
+       vsnprintf(buff, sizeof(buff), fmt, args);
+       va_end(args);
+
+       fatal("%s\n", buff);
+}
+
 void
 warning(const char *fmt, ...)
 {
index 40089e1f74e1f071e9f8624f4d6964b13fa1a03a..72f8ad0662729b12c0da529db4f6591f3159a990 100644 (file)
@@ -90,6 +90,7 @@ extern ff_vecs_t ignr_vecs;
 extern ff_vecs_t stmwpp_vecs;
 extern ff_vecs_t msroute_vecs;
 extern ff_vecs_t cst_vecs;
+extern ff_vecs_t nmn5_vecs;
 
 static
 vecs_t vec_list[] = {
@@ -456,6 +457,12 @@ vecs_t vec_list[] = {
                "CarteSurTable data file",
                "cst"
        },
+       {
+               &nmn5_vecs,
+               "nmn5",
+               "Navigon Mobile Navigator 5 .pdb",
+               "pdb"
+       },
        {
                NULL,
                NULL,